﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using NetfractionHub.Network.Protocol;
using NetfractionHub.Network.Protocol.BASE.Factory;

namespace NetfractionHub.LocalMachine
{
	/// <summary>
	/// The Hub class manages the hub's identity, feature list, and other useful variables.
	/// </summary>
	public class Hub : RemoteMachine.Node
	{
		private DateTime _startTime;

		private Hub()
		{
			InitialiseFeatures();

			this.Identity.NodeType = IdentityNodeTypes.Hub;
			this.Identity.Nickname = Settings.HubSettings.HubIdentity.Name;
			this.Identity.Description = Settings.HubSettings.HubIdentity.Description;

			Version curVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
			this.Identity.ClientVersion = String.Format(System.Globalization.CultureInfo.InvariantCulture, "NetfractionHub {0}.{1}", curVersion.Major, curVersion.Minor);

			this._startTime = DateTime.Now;

			this.Connection = new Network.ClientConnection(null, this);
			this.Connection.State = NetfractionHub.RemoteMachine.ConnectionState.Normal;
		}

		#region Singleton Pattern
		// Use singleton pattern.
		private static Hub _instance;

		/// <summary>
		/// Obtain singleton instance of Hub
		/// </summary>
		/// <returns></returns>
		public static Hub GetInstance()
		{
			// Check instance
			if (Hub._instance == null)
			{
				// Initialise instance
				Hub._instance = new Hub();
			}

			// Return instance
			return Hub._instance;
		}
		#endregion Singleton Pattern

		private void InitialiseFeatures()
		{
			this.Features.Add(Network.Protocol.ProtocolFeature.GetFeatureName(typeof(Network.Protocol.BASE.ProtocolFeatureBASE)), new Network.Protocol.BASE.ProtocolFeatureBASE());
			this.Features.Add(Network.Protocol.ProtocolFeature.GetFeatureName(typeof(Network.Protocol.ADCS.ProtocolFeatureADCS)), new Network.Protocol.ADCS.ProtocolFeatureADCS());
			this.Features.Add(Network.Protocol.ProtocolFeature.GetFeatureName(typeof(Network.Protocol.TIGR.ProtocolFeatureTIGR)), new Network.Protocol.TIGR.ProtocolFeatureTIGR());
			this.Features.Add(Network.Protocol.ProtocolFeature.GetFeatureName(typeof(Network.Protocol.UCMD.ProtocolFeatureUCMD)), new Network.Protocol.UCMD.ProtocolFeatureUCMD());
			this.Features.Add(Network.Protocol.ProtocolFeature.GetFeatureName(typeof(Network.Protocol.PING.ProtocolFeaturePING)), new Network.Protocol.PING.ProtocolFeaturePING());
		}


		private string hubIdentityStringCache = null;
		public string GetHubIdentityString()
		{
			if (hubIdentityStringCache != null)
				return hubIdentityStringCache;

			ProtocolMessageFactory factory = new FactoryINF();
			Dictionary<int, object> factoryParams = new Dictionary<int, object>();
			factoryParams.Add((int)FactoryINF.ParameterEnum.ClientType, (int)this.Identity.NodeType);
			factoryParams.Add((int)FactoryINF.ParameterEnum.NickOrHubName, this.Identity.Nickname);
			factoryParams.Add((int)FactoryINF.ParameterEnum.Description, this.Identity.Description);
			factoryParams.Add((int)FactoryINF.ParameterEnum.ClientVersionIdentifier, this.Identity.ClientVersion);

			if (!string.IsNullOrWhiteSpace(Settings.HubSettings.HubIdentity.FailoverAddresses))
				factoryParams.Add((int)FactoryINF.ParameterEnum.FailoverAddresses, Settings.HubSettings.HubIdentity.FailoverAddresses);

			/*List<ProtocolParameter> extensionParams = (List<ProtocolParameter>)CallMessageExtensions(node, message, extenders, (int)NetfractionHub.Network.Protocol.BASE.Extensibility.HubINFExtensionType.Parameter, null);
			if (extensionParams != null && extensionParams.Count > 0)
			{
			// this used to be in the HandlerSUP code.
			}*/

			hubIdentityStringCache = factory.Create(ProtocolMessage.MessageTypeEnum.Info, factoryParams).ToString();

			return hubIdentityStringCache;
		}

		/// <summary>
		/// The time the hub was started.
		/// </summary>
		public DateTime StartTime
		{
			get { return _startTime; }
			set { _startTime = value; }
		}
	}
}
